package gwin.com.numbers;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * Created by YuZui on 2020/6/18 0018.
 */
public class GameView extends View {
    private int width;
    private int height;
    private int gridWidth;
    private int margin;
    private int gridPadding = 1;
    final Game game;
    private final int remain = 5;
    private final Paint pCursor;
    private final Paint pKnown;
    private final Paint pUnknown;
    private final Paint pOutLine;
    private final Paint pOpened;
    private final Paint txtPaint;
    private final float txtHeight;

    public GameView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        game = new Game();
        pCursor = new Paint();
        pCursor.setColor(Color.YELLOW);
        pCursor.setStyle(Paint.Style.FILL);
        pOutLine = new Paint();
        pOutLine.setColor(Color.RED);
        pOutLine.setStyle(Paint.Style.STROKE);
        pOutLine.setStrokeWidth(2);
        pKnown = new Paint();
        pKnown.setColor(Color.DKGRAY);
        pKnown.setStyle(Paint.Style.STROKE);
        pUnknown = new Paint();
        pUnknown.setColor(Color.WHITE);
        pUnknown.setStyle(Paint.Style.FILL);
        pOpened = new Paint();
        pOpened.setColor(Color.WHITE);
        pOpened.setStyle(Paint.Style.FILL);
        txtPaint = new Paint();
        txtPaint.setTextSize(18);
        txtPaint.setAntiAlias(true);
        Paint.FontMetrics fm = txtPaint.getFontMetrics();
        txtHeight = (float) Math.ceil(fm.descent - fm.ascent);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec);
//        height = MeasureSpec.getSize(heightMeasureSpec);
        gridWidth = (width - remain) / game.LENGTH;
        int remain = width - gridWidth * game.LENGTH;
        margin = remain / 2;

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.BLACK);
        for (int i = 0; i < game.LENGTH; i++) {
            for (int j = 0; j < game.LENGTH; j++) {
                int l = margin + gridPadding + i * gridWidth;
                int t = margin + gridPadding + j * gridWidth;
                int r = l + gridWidth - gridPadding;
                int b = t + gridWidth - gridPadding;
                if (i == game.curX && j == game.curY) {
                    canvas.drawRect(l, t, r, b, pCursor);
                } else {
                    if (game.grids[i][j].isUnknown) {
                        canvas.drawRect(l, t, r, b, pUnknown);
                    } else {
                        canvas.drawRect(l, t, r, b, pKnown);
                    }
                }
                boolean isError = game.grids[i][j].sameList.size() > 0;
                if (game.grids[i][j].isUnknown) {
                    int fillNumber = game.grids[i][j].fillNumber;
                    if (fillNumber > 0) {
                        float txtWidth = txtPaint.measureText("" + fillNumber, 0, 1);
                        txtPaint.setColor(isError ? Color.RED : Color.DKGRAY);
                        canvas.drawText("" + fillNumber, l + gridWidth / 2 - txtWidth / 2, t + gridWidth / 2 + txtHeight / 4, txtPaint);
                    }
                } else {
                    int number = game.grids[i][j].number;
                    float txtWidth = txtPaint.measureText("" + number, 0, 1);
                    txtPaint.setColor(isError ? Color.RED : Color.LTGRAY);
                    canvas.drawText("" + number, l + gridWidth / 2 - txtWidth / 2, t + gridWidth / 2 + txtHeight / 4, txtPaint);
                }
            }
        }
        canvas.drawRect(margin, margin, width - margin, width - margin, pOutLine);
        canvas.drawLine(margin, margin + gridWidth * 3, width - margin, margin + gridWidth * 3, pOutLine);
        canvas.drawLine(margin, margin + gridWidth * 6, width - margin, margin + gridWidth * 6, pOutLine);
        canvas.drawLine(margin + gridWidth * 3, margin, margin + gridWidth * 3, width - margin, pOutLine);
        canvas.drawLine(margin + gridWidth * 6, margin, margin + gridWidth * 6, width - margin, pOutLine);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (event.getRepeatCount() > 0) return true;
        if (game.isGameOver) return false;
        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK:
                return false;
            case KeyEvent.KEYCODE_DPAD_UP:
                game.up();
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                game.down();
                break;
            case KeyEvent.KEYCODE_DPAD_LEFT:
                game.left();
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                game.right();
                break;
            case KeyEvent.KEYCODE_DPAD_CENTER:
                break;
            case KeyEvent.KEYCODE_MENU:
            case KeyEvent.KEYCODE_STAR:
            case KeyEvent.KEYCODE_POUND:
                game.eraseNumber();
                break;
            case KeyEvent.KEYCODE_1:
            case KeyEvent.KEYCODE_2:
            case KeyEvent.KEYCODE_3:
            case KeyEvent.KEYCODE_4:
            case KeyEvent.KEYCODE_5:
            case KeyEvent.KEYCODE_6:
            case KeyEvent.KEYCODE_7:
            case KeyEvent.KEYCODE_8:
            case KeyEvent.KEYCODE_9:
                game.fillNumber(keyCode - KeyEvent.KEYCODE_0);
                break;
        }
        invalidate();//所有动作后都要刷新一下
        return true;
    }

    public void setGameListener(Game.GameListener gameOverListener) {
        game.setGameListener(gameOverListener);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int _x = 0;
        int _y = 0;
        float x = event.getX();
        float y = event.getY();
        for (int i = 0; i < game.LENGTH; i++) {
            if (x > margin + gridWidth * i) {
                _x = i;
                if (x < margin + gridWidth * (i + 1)) {
                    break;
                }
            }
        }
        for (int i = 0; i < game.LENGTH; i++) {
            if (y > margin + gridWidth * i) {
                _y = i;
                if (y < margin + gridWidth * (i + 1)) {
                    break;
                }
            }
        }
        game.curX = _x;
        game.curY = _y;
        invalidate();
        return super.onTouchEvent(event);
    }
}
